Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[linux] fix: memory-mapped file, stat: No such file or directory #329

Merged
merged 2 commits into from
Jan 9, 2025

Conversation

jones2024gh
Copy link
Contributor

Describe the bug
Since lsof-4.96.0, run lsof with old linux kernel (e.g. linux-2.6),
lsof would print error message "stat: No such file or directory"
when visiting memory-mapped files; but /bin/stat could visit it without issue.
lsof-4.95.0 and earlier does not have this issue.

  • 4.99.4 fail
  • 4.99.3 fail
  • 4.96.0 fail
  • 4.95.0 pass
  • 4.92.0 pass

In old linux kernel (e.g. linux-2.6) which does not have this feature: Commit
6b4e306aa3dc ("ns: proc files for namespace naming policy."), means this path
"/proc/self/ns" is not existed. Since lsof-4.96.0 with Commit dbad150 ("
[linux] obtain correct information of memory-mapped file."), compare_mntns()
would misunderstand it is in a different mount namespace if "/proc/self/ns" is
not existed, returns -1, go through map_files lookup, and finally lead to lsof
gets failed with error message "stat: No such file or directory".

If "/proc/self/ns" or its underlying path is not existed, compare_mntns()
returns 0 instead of -1, in order to go through stat_directly as old days.

To Reproduce
Steps to reproduce the behavior:

  1. Run 'lsof -p 1'
  2. See error

Expected behavior
Should not print 'stat: No such file or directory'.

Program output

# lsof -p 1
COMMAND PID USER  FD   TYPE DEVICE SIZE/OFF NODE NAME
init      1 user cwd    DIR   31,6      339  352 /
init      1 user rtd    DIR   31,6      339  352 /
init      1 user txt    REG   31,6   694544 5323 /bin/busybox
init      1 user mem    REG   31,6          4499 /lib/ld-uClibc-0.9.33.2.so (stat: No such file or directory)
init      1 user mem    REG   31,6          4400 /lib/libcrypt-0.9.33.2.so (stat: No such file or directory)
init      1 user mem    REG   31,6          4446 /lib/public/liblogintoken.so (stat: No such file or directory)
init      1 user mem    REG   31,6          4374 /lib/libm-0.9.33.2.so (stat: No such file or directory)
init      1 user mem    REG   31,6          4343 /lib/libuClibc-0.9.33.2.so (stat: No such file or directory)
init      1 user mem    REG   31,6          4434 /lib/libgcc_s.so.1 (stat: No such file or directory)
init      1 user   0u   CHR    5,1      0t0   17 /dev/console
init      1 user   1u   CHR    5,1      0t0   17 /dev/console
init      1 user   2u   CHR    5,1      0t0   17 /dev/console
# /bin/stat /lib/ld-uClibc-0.9.33.2.so
  File: "/lib/ld-uClibc-0.9.33.2.so"
  Size: 31568           Blocks: 62         IO Block: 1024   regular file
Device: 1f06h/7942d     Inode: 4499        Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (    0/ test)   Gid: (    0/    root)
Access: 2024-12-16 21:51:20.000000000
Modify: 2024-12-16 21:51:20.000000000
Change: 2024-12-16 21:51:20.000000000

Environment (please complete the following information):

  • Kernel: linux-2.6.36
  • OS: embedded linux with customized build
  • lsof Version: 4.99.4

In old linux kernel (e.g. linux-2.6) which does not have this feature: Commit
6b4e306aa3dc ("ns: proc files for namespace naming policy."), means this path
"/proc/self/ns" is not existed. Since lsof-4.96.0 with Commit dbad150 ("
[linux] obtain correct information of memory-mapped file."), compare_mntns()
would misunderstand it is in a different mount namespace if "/proc/self/ns" is
not existed, returns -1, go through map_files lookup, and finally lead to lsof
gets failed with error message "stat: No such file or directory".

If "/proc/self/ns" or its underlying path is not existed, compare_mntns()
returns 0 instead of -1, in order to go through stat_directly as old days.

Signed-off-by: Jones Syue <[email protected]>
@jiegec
Copy link
Contributor

jiegec commented Jan 8, 2025

Nice observation! Regarding the code change, maybe we could add some comments on the logic behind comparison: when it is regarded as different, and how it works in different kernel versions.

Add comments:
Compare the inode number of mount namespace, to see if target process is in a
different mount namespace from lsof process: return 0 (false) means mount
namespace is the same, and return 1 (true) means mount namespace is different.
Note that legacy linux kernel (e.g. linux-2.6) might not have this mount
namespace path, so makes this case return 0 (false) and acts as old days.

Signed-off-by: Jones Syue <[email protected]>
@jones2024gh
Copy link
Contributor Author

Hello @jiegec

Thank you for kind feedback! Add comments and hope im doing this in the correct way :)

@jiegec jiegec merged commit a682269 into lsof-org:master Jan 9, 2025
15 of 16 checks passed
@jones2024gh
Copy link
Contributor Author

Thank you @jiegec and your time :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants